# -*- coding: utf-8 -*-

'''
慈善管理函数
'''
from ...pao_python.pao.data import process_db, dataframe_to_list, DataProcess, DataList, get_cur_time
import pandas as pd
import uuid
import datetime
import re
import hashlib
from enum import Enum
from ...service.mongo_bill_service import MongoBillFilter
from ...pao_python.pao.service.security.security_service import RoleService
from ...pao_python.pao.service.security.security_utility import get_current_account_id
from ...service.common import insert_data, find_data, update_data, delete_data, get_condition, get_info
from ...service.buss_pub.bill_manage import BillManageService, OperationType, TypeId, Status
from server.pao_python.pao.service.data.mongo_db import MongoService, MongoFilter, C, N, F, as_date
from ..buss_pub.personnel_organizational import UserType
from server.pao_python.pao.data import process_db
from ...service.common import get_current_user_id, get_current_role_id, get_user_id_or_false, Observer, getAddBillSession
import calendar
from ...service.buss_pub.message_manage import MessageManageService

# 项目状态


class ProjectStatus(Enum):
    # 未开始
    ready = '未开始'
    # 进行中
    progress = '进行中'
    # 已结束
    finish = '已结束'

# 捐赠类型


class DonateType(Enum):
    # 个人
    personal = '个人'
    # 已结束
    fund = '基金'

# 捐赠支付状态


class DonatePayStatus(Enum):
    # 未付款
    unpay = '未付款'
    # 已付款
    finish = '已付款'

# 是否匿名


class IsAnonymous(Enum):
    # 是
    yes = '是'
    # 否
    no = '否'

# 募捐状态


class Auditstatus(Enum):
    # 通过
    adopt = '通过'
    # 不通过
    reject = '不通过'
    # 待审批
    unaudited = '待审批'
    # 未拨款
    unpay = '未拨款'
    # 待审批拨款
    waitpayed = '待拨款'
    # 已拨款
    payed = '已拨款'

# 捐款使用状态


class DonateUsestatus(Enum):
    # 未使用
    unuse = '未使用'
    # 已使用
    used = '已使用'


class CharitableManageService(MongoService, Observer):
    ''' 任务管理 '''
    Charitable_Donate = 'PT_Charitable_Donate'
    Charitable_Project = 'PT_Charitable_Project'
    Charitable_Recipient = 'PT_Charitable_Recipient'
    Charitable_Appropriation = 'PT_Charitable_Appropriation'
    Charitable_Society = 'PT_Charitable_Society'
    Charitable_Record = 'PT_Charitable_Record'
    Third_Trade_Record = 'IEC_third_part_trade_record'
    Volunteer_Service_Category = 'PT_Volunteer_Sservice_Category'
    PT_Message = 'PT_Message'
    PT_Assessment_Template = 'PT_Assessment_Template'

    def __init__(self, db_addr, db_port, db_name, db_user, db_pwd, inital_password, session):
        self.db_addr = db_addr
        self.db_port = db_port
        self.db_name = db_name
        self.db_user = db_user
        self.db_pwd = db_pwd
        self.inital_password = inital_password
        self.session = session
        self.bill_manage_server = BillManageService(
            self.db_addr, self.db_port, self.db_name, self.db_user, self.db_pwd, self.inital_password, self.session)
        self.bill_manage_server2 = BillManageService(
            self.db_addr, self.db_port, self.db_name, self.db_user, self.db_pwd, self.inital_password,  getAddBillSession())
        self.MessageManageService = MessageManageService(
            self.db_addr, self.db_port, self.db_name, self.db_user, self.db_pwd, self.inital_password, self.session)

    def update(self, data):
        self.setPayStatus(data)
        print("========测试========唯一订单号："+str(data)+"=======================")

    def get_session_user_islogin(self):
        if get_user_id_or_false(self.session) == False:
            return False
        else:
            return True

    # 根据时间给予一个项目状态
    def add_project_status(self, begin_date, end_date):
        now_date = get_cur_time()
        if begin_date > now_date:
            return ProjectStatus.ready.value
        elif now_date >= begin_date and end_date >= now_date:
            return ProjectStatus.progress.value
        elif now_date > end_date:
            return ProjectStatus.finish.value

    def get_charitable_information_list(self, org_list, condition, page, count):
        '''获取慈善信息列表
        Arguments:
            condition   {dict}      条件
            page        {number}    页码
            count       {number}    条数
        '''

        monthData = condition['month'].split('-')
        thisMonthDates = calendar.monthrange(
            int(monthData[0]), int(monthData[1]))

        begin_date = str(condition['month']) + '-01 00:00:00'
        end_date = str(condition['month']) + '-' + \
            str(thisMonthDates[1]) + ' 23:59:59'
        begin_date = datetime.datetime.strptime(
            begin_date, "%Y-%m-%d %H:%M:%S")
        end_date = datetime.datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S")

        newCondition = {}
        newCondition['begin_date'] = begin_date
        newCondition['end_date'] = end_date
        max = 99
        return {
            # 获取项目列表
            # 'project_list': self.get_charitable_project_list(org_list, condition, 1, 1),
            # 获取捐款列表
            'donate_list': self.get_charitable_donate_list(org_list, newCondition, 1, max),
            # 获取受助列表
            'recipient_list': self.get_charitable_recipient_apply_list2(org_list, newCondition, 1, max),
            # 获取审核列表
            'appropriation_list': self.get_charitable_appropriation_list(org_list, newCondition, 1, max),
        }

    def get_charitable_project_list(self, org_list, condition, page, count):
        '''获取慈善项目列表
        Arguments:
            condition   {dict}      条件
            page        {number}    页码
            count       {number}    条数
        '''
        keys = ['id', 'name', 'project_status', 'intention']
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.lookup_bill('PT_User', 'creator', 'id', 'creator')
        _filter.lookup_bill('PT_User', 'organization_id',
                            'id', 'organization')
        _filter.match((C('id') == values['id'])
                      & (C('name').like(values['name']))
                      & (C('project_intention').like(values['intention']))
                      & (C('organization_id').inner(org_list)))

        if 'project_status' in condition:
            now_date = get_cur_time()
            if condition['project_status'] == ProjectStatus.ready.value:
                _filter.match(C('begin_date') > now_date)
            elif condition['project_status'] == ProjectStatus.progress.value:
                _filter.match((now_date >= C('begin_date'))
                              & (C('end_date') >= now_date))
            elif condition['project_status'] == ProjectStatus.finish.value:
                _filter.match(now_date > C('end_date'))

        _filter.add_fields({
            # 'show_begin_date': self.ao.date_to_string('$begin_date', "%Y-%m-%d %H:%M:%S"),
            # 'show_end_date': self.ao.date_to_string('$end_date', "%Y-%m-%d %H:%M:%S"),
            'project_creator_name': '$creator.name',
            'organization_name': '$organization.name'
        })
        _filter.sort({'create_date': -1})
        _filter.project({
            '_id': 0,
            'creator': 0,
            'organization': 0,
        })

        res = self.page_query(_filter, self.Charitable_Project, page, count)

        for result in res.get('result'):
            result['donate_money_sum'] = self.get_charitable_donate_sum(
                result['id'])
            result['project_status'] = self.add_project_status(
                result['begin_date'], result['end_date'])
        return res

    def get_charitable_donate_sum(self, id):
        _filter = MongoBillFilter()
        _filter.match((C('donate_project_id') == id)
                      & (C('pay_status') == DonatePayStatus.finish.value))

        res = self.query(_filter, self.Charitable_Donate)

        sum = 0

        for index in range(len(res)):
            sum += res[index]['donate_money']

        return sum

    def update_charitable_project(self, data):
        '''新增或者修改慈善项目'''
        res = 'Fail'
        # 创建者
        data['creator'] = get_current_user_id(self.session)
        # 日期区间
        if 'project_time' in list(data.keys()):
            begin_date = data['project_time'][0][0:10] + \
                ' '+data['project_time'][0][11:19]
            data['begin_date'] = datetime.datetime.strptime(
                begin_date, '%Y-%m-%d %H:%M:%S')
            end_date = data['project_time'][1][0:10] + \
                ' '+data['project_time'][1][11:19]
            data['end_date'] = datetime.datetime.strptime(
                end_date, '%Y-%m-%d %H:%M:%S')

            del(data['project_time'])

        if 'id' in list(data.keys()):
            bill_id = self.bill_manage_server.add_bill(
                OperationType.update.value, TypeId.charitableProject.value, data, self.Charitable_Project)
            if bill_id:
                res = 'Success'
        else:
            bill_id = self.bill_manage_server.add_bill(
                OperationType.add.value, TypeId.charitableProject.value, data, self.Charitable_Project)
            if bill_id:
                res = 'Success'
        return res

    def get_charitable_donate_list(self, org_list, condition, page, count):
        '''获取捐赠列表
        Arguments:
            condition   {dict}      条件
            page        {number}    页码
            count       {number}    条数
        '''

        # 默认个人
        if 'donate_type' not in condition:
            condition['donate_type'] = DonateType.personal.value
        else:
            if condition['donate_type'] == '':
                del(condition['donate_type'])

        keys = ['id', 'ids', 'donate_name', 'intention',
                'donate_project_id', 'pay_status', 'status', 'begin_date', 'end_date', 'donate_type', 'status']
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.lookup_bill(self.Charitable_Project,
                            'donate_project_id', 'id', 'donate_project')
        _filter.match_bill((C('id') == values['id'])
                           & (C('donate_project_id') == values['donate_project_id'])
                           & (C('pay_status') == values['pay_status'])
                           & (C('status') == values['status'])
                           & (C('donate_type') == values['donate_type'])
                           & (C('donate_name').like(values['donate_name']))
                           & (C('donate_intention').like(values['intention']))
                           & (C('organization_id').inner(org_list))
                           & (C('id').inner(values['ids'])))

        if 'donate_type' in condition and condition['donate_type'] == '基金':
            if 'all' not in condition:
                role_id = get_current_role_id(self.session)
                _filter.lookup_bill('PT_Approval_Process', 'id', 'business_id', 'process')\
                    .add_fields({'new_field': self.ao.array_filter("$process", "aa", ((F('$aa.approval_user_id') == role_id) & (F('$aa.step_no') == (F('step_no'))) & (F('$aa.status') == '待审批')).f)}).match((C("new_field") != None) & (C("new_field") != []))
            else:
                # 获取全部的
                del(condition['all'])
                _filter.lookup_bill('PT_Approval_Process', 'id', 'business_id', 'process')\
                    .add_fields({'new_field': self.ao.array_filter("$process", "aa", ((F('$aa.step_no') == (F('step_no')))).f)}).match((C("new_field") != None) & (C("new_field") != []))

        if 'begin_date' in condition and 'end_date' in condition:
            _filter.match_bill(C('create_date') >= condition['begin_date'])
            _filter.match_bill(C('create_date') <= condition['end_date'])

        _filter.add_fields({
            'donate_project_name': '$donate_project.project_name'
        })
        _filter.lookup_bill('PT_Charitable_Record', 'id', 'donate_id', 'record_info')\
            .add_fields({'apply_count': self.ao.size('$record_info'), })
        _filter.sort({'modify_date': -1})
        _filter.project({
            '_id': 0,
            'donate_project': 0,
            'new_field._id': 0,
            'process._id': 0,
            'record_info': 0,
        })
        res = self.page_query(
            _filter, self.Charitable_Donate, page, count)

        _self = self

        for result in res.get('result'):

            recipient_id = ''
            if 'recipient_id' in condition:
                recipient_id = condition['recipient_id']

            # 获取在记录表的记录
            donate_record = self.get_charitable_donate_record(
                result['id'], recipient_id)

            # 补充冻结金额
            result['freeze_money'] = float(donate_record['freeze_money'])
            # 补充已使用金额
            result['payed_money'] = float(donate_record['payed_money'])
            # 补充剩余金额
            result['surplus_money'] = result['donate_money'] - \
                donate_record['freeze_money'] - donate_record['payed_money']

            # 补充去向信息
            result['recipient_info'] = donate_record['recipient_info']

            # 冠名基金是没有匿名的
            if 'is_anonymous' in result:
                if result['is_anonymous'] == IsAnonymous.yes.value:
                    result['donate_name'] = '匿名'
        return res

    def get_charitable_donate_record(self, id, recipient_id):
        status = [Auditstatus.unaudited.value, Auditstatus.adopt.value]
        _filter = MongoBillFilter()
        _filter.match_bill((C('donate_id') == id) &
                           (C('status').inner(status)))

        if recipient_id != '':
            # 这是有传入recipient_id的情况
            _filter.match_bill((C('recipient_id') == recipient_id))
            _filter.lookup_bill(self.Charitable_Recipient,
                                'recipient_id', 'id', 'recipient_info')
        else:
            # 这是没传入的情况，默认拿全部并且已经通过的
            _filter.lookup_bill(self.Charitable_Recipient,
                                'recipient_id', 'id', 'recipient_info')

        _filter.project({
            '_id': 0,
            'recipient_info._id': 0,
        })

        res = self.query(_filter, self.Charitable_Record)

        payed_money = 0
        freeze_money = 0
        recipient_info = []

        for index in range(len(res)):
            # 冻结
            if res[index]['status'] == Auditstatus.unaudited.value:
                freeze_money += res[index]['freeze_money']
            if res[index]['status'] == Auditstatus.adopt.value:
                payed_money += res[index]['freeze_money']

                # 补充状态为通过的募捐信息
                # 补充使用的金额，在去向列表用到
                res[index]['recipient_info'][0]['give_money'] = '￥' + \
                    str(res[index]['freeze_money'])
                recipient_info.append(res[index]['recipient_info'][0])

        returnData = {}
        returnData['payed_money'] = payed_money
        returnData['freeze_money'] = freeze_money
        returnData['recipient_info'] = recipient_info
        return returnData

    def update_charitable_donate(self, data):
        '''新增慈善捐赠'''
        res = 'Fail'

        # 创建者
        data['donate_user_id'] = get_current_user_id(self.session)
        # 默认未付款
        data['pay_status'] = DonatePayStatus.unpay.value
        # 捐款默认通过
        data['status'] = Auditstatus.adopt.value

        if 'id' in list(data.keys()) and data['id'] == 'project_id':
            del(data['id'])

        if 'id' in list(data.keys()):
            bill_id = self.bill_manage_server.add_bill(
                OperationType.update.value, TypeId.charitableDonate.value, data, self.Charitable_Donate)
            if bill_id:
                res = 'Success'
        else:
            bill_id = self.bill_manage_server.add_bill(
                OperationType.add.value, TypeId.charitableDonate.value, data, self.Charitable_Donate)
            if bill_id:
                res = 'Success'
        return res

    # 修改审批流程操作
    def changeSpProcess(self, data, typeId, table, stepType, roleName, extra=[], callback=False):

        res = 'Fail'
        # 如果带有id，编辑状态
        if 'id' in data.keys():

            role_id = get_current_role_id(self.session)
            user_id = get_current_user_id(self.session)

            _filter_process = MongoBillFilter()
            _filter_process.match_bill((C('business_id') == data['id']) & (
                C('approval_user_id') == role_id) & (C('step_no') == data['step_no'])).project({'_id': 0})
            process_data = self.query(
                _filter_process, 'PT_Approval_Process')

            if len(process_data) > 0 and 'sp_status' in data.keys():
                if process_data[0]['status'] != Auditstatus.unaudited.value:
                    return '无法重复审核'
                if data['sp_status'] == Auditstatus.adopt.value:
                    # 审批状态
                    process_data[0]['status'] = data['sp_status']
                    # 主数据
                    data['status'] = data['status']

                    _filter_process_length = MongoBillFilter()
                    _filter_process_length.match_bill(
                        (C('business_id') == data['id'])).project({'_id': 0})
                    process_data_length = len(self.query(
                        _filter_process_length, 'PT_Approval_Process'))

                    if process_data_length != data['step_no']:
                        # 如果不是最后一步，就变成下一步
                        data['step_no'] = data['step_no'] + 1
                    else:
                        # -1表示完成了
                        data['step_no'] = -1
                        process_data[0]['step_no'] = -1

                elif data['sp_status'] == '不通过':
                    # 审批状态
                    process_data[0]['status'] = data['sp_status']
                    # 主数据
                    data['status'] = data['status']
                elif data['sp_status'] == '打回':
                    # 审批状态
                    process_data[0]['status'] = data['sp_status']
                    # 主数据
                    data['status'] = data['status']

            # 删掉审批结果和审批可能附带的
            if 'sp_status' in data:
                del(data['sp_status'])
            if 'sp_msg' in data:
                process_data[0]['opinion'] = [data['sp_msg']]
                
            # 补充审核操作人
            process_data[0]['proccess_user_id'] = user_id

            # 有额外添加的数据
            if len(extra) > 0:
                for index in extra:
                    data[index] = extra[index]

            # 进入审批状态，并修改主数据
            bill_id = self.bill_manage_server.add_bill(
                OperationType.update.value, typeId, [data, process_data[0]], [table, 'PT_Approval_Process'])
            if bill_id:
                res = 'Success'

            if callback:
                callback()
        else:
            # 新增状态

            # 缓存id转回主键ID
            if 'temp_id' in data:
                data['id'] = data['temp_id']
                del(data['temp_id'])

            # 找到Approval_Define表的规则
            _filter = MongoBillFilter()
            _filter.match_bill((C('approval_type') == stepType) & (C('type') == roleName))\
                .project({'_id': 0})
            res_define = self.query(_filter, 'PT_Approval_Define')
            if len(res_define) > 0 and len(res_define[0]['approval_list']) > 0:
                process_data_list = []
                table_list = []
                for approval in res_define[0]['approval_list']:
                    data_info = get_info(data, self.session)
                    process_data = {"define_id": res_define[0]['id'], "business_id": data_info['id'], "approval_user_id":
                                    approval['approval_user_id'], "step_no": approval['step_no'], "opinion": [], "status": "待审批"}

                    process_data_list.append(
                        get_info(process_data, self.session))
                    table_list.append('PT_Approval_Process')

                process_data_list.append(data_info)
                table_list.append(table)

                # 进入审批状态，并新增主数据
                bill_id = self.bill_manage_server.add_bill(
                    OperationType.add.value, typeId, process_data_list, table_list)
                if bill_id:
                    res = 'Success'
            else:
                return '无权限'
        return res

    def get_charitable_recipient_apply_list(self, org_list, condition, page, count):
        '''获取个人募捐申请列表
        Arguments:
            condition   {dict}      条件
            page        {number}    页码
            count       {number}    条数
        '''
        keys = ['id', 'apply_name', 'status',
                'apply_type', 'begin_date', 'end_date', 'all']
        values = self.get_value(condition, keys)
        role_id = get_current_role_id(self.session)
        _filter = MongoBillFilter()

        _filter.match_bill((C('id') == values['id'])
                           & (C('status') == values['status'])
                           & (C('apply_type') == values['apply_type'])
                           & (C('apply_name').like(values['apply_name']))
                           & (C('organization_id').inner(org_list)))

        if 'is_mine' in condition and condition['is_mine'] == True:
            user_id = get_user_id_or_false(self.session)
            print(user_id)
            if user_id == False:
                return '请重新登录！'
            _filter.match_bill((C('apply_user_id') == user_id))

        if 'all' not in condition:
            _filter.lookup_bill('PT_Approval_Process', 'id', 'business_id', 'process')\
                .add_fields({'new_field': self.ao.array_filter("$process", "aa", ((F('$aa.approval_user_id') == role_id) & (F('$aa.step_no') == (F('step_no'))) & (F('$aa.status') == '待审批')).f)}).match((C("new_field") != None) & (C("new_field") != []))
        else:
            del(condition['all'])
            _filter.lookup_bill('PT_Approval_Process', 'id', 'business_id', 'process')\
                .add_fields({'new_field': self.ao.array_filter("$process", "aa", ((F('$aa.step_no') == (F('step_no')))).f)}).match((C("new_field") != None) & (C("new_field") != []))
        _filter.lookup_bill(self.Charitable_Appropriation,
                            'id', 'recipient_id', 'appropriation_info')
        _filter.lookup_bill(self.Charitable_Donate,
                            'project_id', 'id', 'project_info')
        _filter.add_fields({
            'donate_ids': '$appropriation_info.donate_ids',
            'appropriation_id': '$appropriation_info.id',
        })

        if 'begin_date' in condition and 'end_date' in condition:
            _filter.match_bill(C('create_date') >= condition['begin_date'])
            _filter.match_bill(C('create_date') <= condition['end_date'])

        _filter.sort({'modify_date': -1})
        _filter.project({'_id': 0, 'new_field._id': 0,
                         'process._id': 0, 'appropriation_info': 0, 'project_info._id': 0})

        res = self.page_query(
            _filter, self.Charitable_Recipient, page, count)
        return res

    def get_charitable_recipient_apply_list2(self, org_list, condition, page, count):
        '''获取个人募捐申请列表
        Arguments:
            condition   {dict}      条件
            page        {number}    页码
            count       {number}    条数
        '''
        keys = ['id', 'apply_name', 'status',
                'apply_type', 'begin_date', 'end_date']
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.match_bill((C('id') == values['id'])
                           & (C('status') == values['status'])
                           & (C('apply_type') == values['apply_type'])
                           & (C('apply_name').like(values['apply_name']))
                           & (C('organization_id').inner(org_list)))

        if 'begin_date' in condition and 'end_date' in condition:
            _filter.match_bill(C('create_date') >= condition['begin_date'])
            _filter.match_bill(C('create_date') <= condition['end_date'])

        _filter.sort({'create_date': -1})
        _filter.project({'_id': 0})

        res = self.page_query(
            _filter, self.Charitable_Recipient, page, count)
        return res

    # 回滚记录表
    def rollback_charitable_record(self, appropriation_id, status):

        # 回滚申请表的记录
        data = {
            'id': appropriation_id,
            'status': status,
        }

        self.bill_manage_server.add_bill(
            OperationType.update.value, TypeId.charitableAppropriation.value, data, self.Charitable_Appropriation)

        # 回滚记录表的记录
        _filter = MongoBillFilter()
        _filter.match_bill((C('appropriation_id') == appropriation_id))

        res = self.query(_filter, self.Charitable_Record)

        for index in range(len(res)):
            # 冻结
            data = {
                'id': res[index]['id'],
                'status': status,
            }
            self.bill_manage_server.add_bill(
                OperationType.update.value, TypeId.charitableRecord.value, data, self.Charitable_Record)

        return True

    def getSpRes(self, data):
        # 审批流程的数据
        spData = {
            'id': data['id'],
            'sp_status': data['sp_status'],
            'status': data['status'],
            'step_no': data['step_no'],
        }
        if 'sp_msg' in data:
            spData['sp_msg'] = data['sp_msg']
        return spData

    def update_charitable_recipient_apply(self, data):
        '''新增或者修改募捐申请'''
        res = 'Fail'

        # 带有need_login的必须登录，未登录返回
        if 'need_login' in data and get_user_id_or_false(self.session) == False:
            del(data['need_login'])
            return '请先登录'

        # 根据apply_type确定申请表类型
        if data['apply_type'] == '个人':
            define_type = 'recipientApply'
        elif data['apply_type'] == '机构':
            define_type = 'organizationApply'

        # 带有id，编辑状态
        if 'id' in list(data.keys()):
            # 进入审批流程
            if 'is_sp' in list(data.keys()):
                # 统一不通过
                if data['sp_status'] == Auditstatus.reject.value:
                    # 在第四步的不通过，需要通过appropriation_id把记录表和申请表设为不通过
                    # 首先获取appropriation信息
                    if data['step_no'] == 4:
                        _filter = MongoBillFilter()
                        _filter.match_bill((C('id') == data['id']) &
                                           (C('status') == Auditstatus.unaudited.value))
                        _filter.project({
                            '_id': 0,
                        })
                        appropriation_info = self.query(
                            _filter, self.Charitable_Appropriation)

                        # 该申请ID没有找到待审批的数据，非法操作
                        if len(appropriation_info) == 0:
                            return '非法操作！'

                        # 回滚冻结状态
                        self.rollback_charitable_record(
                            appropriation_info[0]['id'], Auditstatus.reject.value)

                    # 进入审批流程
                    # 获取审批数据
                    newData = self.getSpRes(data)
                    # 公共审批流程
                    res = self.changeSpProcess(newData, TypeId.charitableRecipient.value,
                                               self.Charitable_Recipient, define_type, '全部')

                    return res
                if 'step_no' in list(data.keys()):
                    # 步骤1，资料审核
                    if data['step_no'] == 1:
                        # 资料审核，由于不通过都在统一不通过，所以这里肯定是通过的
                        # 进入审批流程
                        # 获取审批数据
                        newData = self.getSpRes(data)
                        # 公共审批流程
                        res = self.changeSpProcess(newData, TypeId.charitableRecipient.value,
                                                   self.Charitable_Recipient, define_type, '全部')
                    elif data['step_no'] == 2:
                        # 补全备案号，由于不通过都在统一不通过，所以这里肯定是通过的
                        # 进入审批流程
                        # 获取审批数据
                        newData = self.getSpRes(data)
                        # 公共审批流程
                        res = self.changeSpProcess(newData, TypeId.charitableRecipient.value,
                                                   self.Charitable_Recipient, define_type, '全部')

                        # 审批流程有误，直接退出，不进行表操作
                        if res != 'Success':
                            return res
                        # 审批流程通过，需要把sp_msg补全为备案号
                        recipient_data = {
                            'id': data['id'],
                            'beianhao': data['sp_msg']
                        }
                        bill_id = self.bill_manage_server.add_bill(
                            OperationType.update.value, TypeId.charitableRecipient.value, recipient_data, self.Charitable_Recipient)

                    elif data['step_no'] == 3:
                        # 提交拨款审核
                        # 如果没有捐款数据，则非法操作
                        if 'donate_ids' not in data:
                            return '非法操作！'

                        # 提交拨款流程，由于不通过都在统一不通过，所以这里肯定是通过的
                        # 进入审批流程
                        # 获取审批数据
                        newData = self.getSpRes(data)
                        # 公共审批流程
                        res = self.changeSpProcess(newData, TypeId.charitableRecipient.value,
                                                   self.Charitable_Recipient, define_type, '全部')

                        # 审批流程有误，直接退出，不进行记录表操作
                        if res != 'Success':
                            return res

                        # 删除审核相关的数据，下面是处理记录表
                        del(data['is_sp'])
                        del(data['sp_status'])
                        del(data['step_no'])

                        # 申请过期时间
                        overdue_date = datetime.datetime.now() + datetime.timedelta(days=7)

                        # 保存创建者ID
                        data['creator'] = get_current_user_id(self.session)
                        # 记录数据的审核状态
                        data['status'] = Auditstatus.unaudited.value
                        # 过期时间
                        data['overdue_date'] = overdue_date

                        params = []
                        tables = []

                        # 先获取申请表的ID
                        data['recipient_id'] = data['id']
                        # 通过get_info函数，先获取申请表主键ID
                        data_info = get_info(data, self.session)

                        for result in data['donate_ids']:
                            params.append({
                                # 捐赠的ID
                                'donate_id': result['id'],
                                # 受助的ID
                                'recipient_id': data['id'],
                                # 申请表的ID
                                'appropriation_id': data_info['id'],
                                # 冻结金额
                                'freeze_money': result['occupy_money'],
                                # 过期时间，七天后
                                'overdue_date': overdue_date,
                                # 增加一个状态
                                'status': Auditstatus.unaudited.value,
                            })
                            tables.append(self.Charitable_Record)

                        # 插入一个申请表和记录表的流程
                        params.append(data_info)
                        tables.append(self.Charitable_Appropriation)
                        bill_id = self.bill_manage_server.add_bill(
                            OperationType.add.value, TypeId.charitableRecord.value, params, tables)

                        if bill_id:
                            res = 'Success'
                    elif data['step_no'] == 4:
                        # 审核拨款，由于不通过都在统一不通过，所以这里肯定是通过的

                        # 进入审批流程
                        # 获取审批数据
                        newData = self.getSpRes(data)
                        # 公共审批流程
                        res = self.changeSpProcess(
                            newData, TypeId.charitableRecipient.value, self.Charitable_Recipient, define_type, '全部')

                        # 审批流程有误，直接退出，不进行记录表操作
                        if res != 'Success':
                            return res
                    elif data['step_no'] == 5:
                        # 确认拨款的界面，由于不通过都在统一不通过，所以这里肯定是通过的
                        # 如果没有募捐表主键数据，则非法操作
                        if 'id' not in data:
                            return '非法操作！'
                        # 根据传入的id，从申请表获取donate_ids
                        _filter = MongoBillFilter()
                        _filter.match_bill((C('id') == data['id']) &
                                           (C('status') == Auditstatus.unaudited.value))
                        _filter.project({
                            '_id': 0,
                        })
                        appropriation_info = self.query(
                            _filter, self.Charitable_Appropriation)

                        # 该申请ID没有找到待审批的数据，非法操作
                        if len(appropriation_info) == 0:
                            return '非法操作！'

                        # 插入主数据的额外数据
                        extra = {
                            'id': appropriation_info[0]['recipient_id'],
                            'status': Auditstatus.adopt.value,
                            'pay_date': get_cur_time(),
                            'donate_ids': appropriation_info[0]['donate_ids']
                        }

                        def proccess_db():
                            # 申请表和记录表都修改
                            self.rollback_charitable_record(
                                appropriation_info[0]['id'], Auditstatus.adopt.value)

                        # 进入审批流程
                        # 获取审批数据
                        newData = self.getSpRes(data)
                        # 公共审批流程
                        res = self.changeSpProcess(
                            newData, TypeId.charitableRecipient.value, self.Charitable_Recipient, define_type, '全部', extra, proccess_db)

                        # 审批流程有误，直接退出，不进行记录表操作
                        if res != 'Success':
                            return res
            else:
                bill_id = self.bill_manage_server.add_bill(
                    OperationType.update.value, TypeId.charitableRecipient.value, data, self.Charitable_Recipient)
                if bill_id:
                    res = 'Success'
        else:
            # 新增一个待审批
            data['apply_user_id'] = get_current_user_id(self.session)
            # 第一步
            data['step_no'] = 1
            data['status'] = Auditstatus.unaudited.value

            data_info = get_info(data, self.session)

            # 带id进不去审批创建流程，但是又不能丢失ID，所以创造一个缓存id
            data_info['temp_id'] = data_info['id']
            del(data_info['id'])
            
            # 接入审批流程
            res = self.changeSpProcess(data, TypeId.charitableRecipient.value,
                                       self.Charitable_Recipient, define_type, '全部')
            # if res == 'Success':
                # # 插入一个消息提醒
                # self.MessageManageService.add_new_message({
                #     # 慈善基金标识
                #     "business_type": 'title_fund',
                #     # 业务ID
                #     "business_id": data_info['temp_id']
                # })
        return res

    def get_volunteer_service_category_list(self, org_list, condition, page, count):
        '''获取志愿者服务类别列表
        Arguments:
            condition   {dict}      条件
            page        {number}    页码
            count       {number}    条数
        '''
        keys = ['id', 'name']
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.match_bill((C('id') == values['id'])
                           & (C('name').like(values['name']))
                           & (C('organization_id').inner(org_list)))
        _filter.sort({'create_date': -1})
        _filter.project({
            '_id': 0,
        })

        res = self.page_query(
            _filter, self.Volunteer_Service_Category, page, count)

        return res

    def update_volunteer_service_category(self, data):
        '''新增或者修改志愿者服务类别'''
        res = 'Fail'

        if 'id' in list(data.keys()):
            bill_id = self.bill_manage_server.add_bill(
                OperationType.update.value, TypeId.volunteerServiceCategory.value, data, self.Volunteer_Service_Category)
            if bill_id:
                res = 'Success'
        else:
            bill_id = self.bill_manage_server.add_bill(
                OperationType.add.value, TypeId.volunteerServiceCategory.value, data, self.Volunteer_Service_Category)
            if bill_id:
                res = 'Success'
        return res

    def get_charitable_appropriation_list(self, org_list, condition, page, count):
        '''获取慈善拨款列表
        Arguments:
            condition   {dict}      条件
            page        {number}    页码
            count       {number}    条数
        '''
        keys = ['id', 'name', 'status', 'begin_date', 'end_date']
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.lookup_bill('PT_User', 'creator', 'id', 'creator')
        _filter.lookup_bill(self.Charitable_Recipient,
                            'id', 'id', 'recipient_info')
        _filter.match_bill((C('id') == values['id'])
                           & (C('name').like(values['name']))
                           & (C('status') == values['status'])
                           & (C('organization_id').inner(org_list)))

        if 'begin_date' in condition and 'end_date' in condition:
            _filter.match_bill(C('create_date') >= condition['begin_date'])
            _filter.match_bill(C('create_date') <= condition['end_date'])

        _filter.add_fields({
            'creator_name': '$creator.name',
            'apply_name': '$recipient_info.apply_name',
            'apply_money': '$recipient_info.apply_money',
        })
        _filter.sort({'create_date': -1})
        _filter.project({
            '_id': 0,
            'creator': 0,
            'recipient_info': 0,
        })

        res = self.page_query(
            _filter, self.Charitable_Appropriation, page, count)

        return res

    def update_charitable_appropriation(self, data):
        '''新增或修改慈善拨款'''
        res = 'Fail'
        # return res

        if 'id' in list(data.keys()):
            # 先把这个删除，不改变数据库
            if 'ids' in list(data.keys()):
                ids_temp = data['ids']
                del(data['ids'])

                # 进入审批流程
            if 'is_sp' in list(data.keys()):
                newData = {}
                newData['id'] = data['id']
                newData['sp_status'] = data['sp_status']
                newData['step_no'] = data['step_no']
                # 进入审批流程
                res = self.changeSpProcess(newData, TypeId.charitableRecipient.value,
                                           self.Charitable_Recipient, 'recipientApply', '全部')
            if res != 'Success':
                return res

            del(data['is_sp'])
            del(data['sp_status'])
            del(data['step_no'])

            # 修改申请表为已通过
            bill_id = self.bill_manage_server.add_bill(
                OperationType.update.value, TypeId.charitableAppropriation.value, data, self.Charitable_Appropriation)

            if bill_id:
                res = 'Success'
                now_date = get_cur_time()
                # 修改募捐表，状态为已拨款
                self.bill_manage_server.add_bill(OperationType.update.value, TypeId.charitableRecipient.value, {
                    'id': data['id'], 'status': Auditstatus.payed.value, 'pay_date': now_date, 'donate_ids': ids_temp}, self.Charitable_Recipient)

                # 遍历改变状态，修改捐赠表为已使用
                if data['status'] == Auditstatus.adopt.value:
                    for id in ids_temp:
                        self.bill_manage_server.add_bill(OperationType.update.value, TypeId.charitableDonate.value, {
                                                         'id': id, 'status': DonateUsestatus.used.value, 'use_id': data['id'], 'use_date': now_date}, self.Charitable_Donate)

        else:

            # 判断是否存在一个等待审批中的申请
            isApplying = self.check_recipient_is_applying(data['id'])

            if(isApplying != False):
                res = {
                    'msg': 'isApplying',
                    'applyingId': isApplying
                }
                return res

            # 进入审批流程
            if 'is_sp' in list(data.keys()):
                newData = {}
                newData['id'] = data['id']
                newData['sp_status'] = data['sp_status']
                newData['step_no'] = data['step_no']
                # 进入审批流程
                res = self.changeSpProcess(newData, TypeId.charitableRecipient.value,
                                           self.Charitable_Recipient, 'recipientApply', '全部')
            if res != 'Success':
                return res

            del(data['is_sp'])
            del(data['sp_status'])
            del(data['step_no'])

            # 现在的时间
            overdue_date = datetime.datetime.now() + datetime.timedelta(days=7)

            # 创建者
            data['creator'] = get_current_user_id(self.session)
            # 审核状态
            data['status'] = Auditstatus.unaudited.value
            # 过期时间
            data['overdue_date'] = overdue_date

            if 'donate_ids' not in data:
                return '非法操作！'

            params = []
            tables = []

            for result in data['donate_ids']:
                param = {}
                # 捐赠的ID
                param['donate_id'] = result['id']
                # 冻结金额
                param['freeze_money'] = result['occupy_money']
                # 过期时间，七天后
                param['overdue_date'] = overdue_date
                # 增加一个状态
                param['status'] = Auditstatus.unaudited.value

                params.append(param)
                tables.append(self.Charitable_Record)

            # 真正的插入一个申请表
            params.append(data)
            tables.append(self.Charitable_Appropriation)
            bill_id = self.bill_manage_server.add_bill(
                OperationType.add.value, TypeId.charitableRecord.value, params, tables)

            if bill_id:
                res = 'Success'
        return res

    def check_recipient_is_applying(self, id):
        '''判断请求是否已经在申请中
        '''
        # 判断该活动是否已经报名过，添加个人状态
        res = False
        Table = self.Charitable_Appropriation

        def process_func(db):
            nonlocal res
            result = find_data(db, Table, {
                'status': '待审批', 'bill_status': 'valid', 'id': id})
            # 已经报名
            if len(result):
                res = result[0]['id']
        process_db(self.db_addr, self.db_port, self.db_name,
                   process_func, self.db_user, self.db_pwd)

        return res

    def get_charitable_society_list(self, org_list, condition, page, count):
        '''获取慈善会资料列表
        Arguments:
            condition   {dict}      条件
            page        {number}    页码
            count       {number}    条数
        '''
        # keys = ['id']
        # values = self.get_value(condition, keys)
        count = 1
        _filter = MongoBillFilter()
        _filter.match_bill((C('organization_id').inner(org_list)))
        _filter.sort({'create_date': -1})
        _filter.project({
            '_id': 0,
        })

        res = self.page_query(
            _filter, self.Charitable_Society, page, count)

        return res

    def update_charitable_society(self, data):
        '''新增或者修改慈善会资料'''
        res = 'Fail'

        if 'id' in data:
            bill_id = self.bill_manage_server.add_bill(
                OperationType.update.value, TypeId.charitableSociety.value, data, self.Charitable_Society)
            if bill_id:
                res = 'Success'
        else:
            bill_id = self.bill_manage_server.add_bill(
                OperationType.add.value, TypeId.charitableSociety.value, data, self.Charitable_Society)
            if bill_id:
                res = 'Success'
        return res

    def get_charitable_title_fund_list(self, org_list, condition, page, count):
        '''获取冠名基金列表
        Arguments:
            condition   {dict}      条件
            page        {number}    页码
            count       {number}    条数
        '''

        condition['donate_type'] = DonateType.fund.value

        return self.get_charitable_donate_list(org_list, condition, page, count)

    def update_charitable_title_fund(self, data):
        '''新增或者修改冠名基金'''
        res = 'Fail'

        # 定义审批类型
        define_type = 'titleFundApply'

        # 带有id，编辑状态
        if 'id' in list(data.keys()):
            # 进入审批流程
            if 'is_sp' in list(data.keys()):
                # 统一不通过
                if data['sp_status'] == Auditstatus.reject.value:
                    # 进入审批流程
                    # 获取审批数据
                    newData = self.getSpRes(data)
                    # 公共审批流程
                    res = self.changeSpProcess(newData, TypeId.charitableRecipient.value,
                                               self.Charitable_Donate, define_type, '全部')

                    return res
                if 'step_no' in list(data.keys()):
                    # 步骤1，资料审核
                    if data['step_no'] == 1:
                        # 资料审核，由于不通过都在统一不通过，所以这里肯定是通过的
                        # 进入审批流程
                        # 获取审批数据
                        newData = self.getSpRes(data)
                        # 公共审批流程
                        res = self.changeSpProcess(newData, TypeId.charitableTitleFund.value,
                                                   self.Charitable_Donate, define_type, '全部')
                    elif data['step_no'] == 2:
                        # 待完成支付，由于不通过都在统一不通过，所以这里肯定是通过的
                        # 进入审批流程
                        # 获取审批数据
                        newData = self.getSpRes(data)
                        # 公共审批流程
                        res = self.changeSpProcess(newData, TypeId.charitableTitleFund.value,
                                                   self.Charitable_Donate, define_type, '全部')

            else:
                bill_id = self.bill_manage_server.add_bill(
                    OperationType.update.value, TypeId.charitableTitleFund.value, data, self.Charitable_Donate)
                if bill_id:
                    res = 'Success'
        else:
            # 新增一个待审批
            data['apply_user_id'] = get_current_user_id(self.session)
            # 第一步
            data['step_no'] = 1
            # 待审批状态
            data['status'] = Auditstatus.unaudited.value
            # 捐赠类型为基金
            data['donate_type'] = DonateType.fund.value
            # 未付款
            data['pay_status'] = DonatePayStatus.unpay.value
            # 补全一个非匿名
            data['is_anonymous'] = '否'

            if 'open_date' in data and len(data['open_date']) == 2:
                # 开始时间
                data['begin_date'] = datetime.datetime.strptime(
                    data['open_date'][0], '%Y-%m-%dT%H:%M:%S.%fZ')
                # 结束时间
                data['end_date'] = datetime.datetime.strptime(
                    data['open_date'][1], '%Y-%m-%dT%H:%M:%S.%fZ')
                # 删掉
                del(data['open_date'])

            # 接入审批流程
            res = self.changeSpProcess(data, TypeId.charitableTitleFund.value,
                                       self.Charitable_Donate, define_type, '全部')
        return res

    def get_recipient_step(self, org_list, condition, page, count):
        # 暂时来说个人和机构流程都一样，不同的话可以通过condition['step_type']区分
        if 'step_type' not in condition:
            return '非法操作！'

        if condition['step_type'] == '个人' or condition['step_type'] == '机构':
            return [{
                'step_name': '填写申请信息',
            }, {
                'step_name': '资料审核',
            }, {
                'step_name': '申请备案号',
            }, {
                'step_name': '拨款',
            }, {
                'step_name': '拨款审核',
            }, {
                'step_name': '拨款确认',
            }, {
                'step_name': '完成',
            }]
        elif condition['step_type'] == '基金':
            return [{
                'step_name': '填写申请信息',
            }, {
                'step_name': '资料审核',
            }, {
                'step_name': '捐款',
            }, {
                'step_name': '完成',
            }]

    def setPayStatus(self, data):

        # 传过来的数据一个是第三方订单ID
        out_trade_no = data['out_trade_no']
        # 另一个是原样返回的
        attach = data['attach']

        checkTypeList = ['donate', 'titlefund']

        if attach not in checkTypeList or attach == '' or out_trade_no == '':
            return False

        # 转发到checkPayStatus处理
        self.checkPayStatus({
            'checkType': attach,
            'out_trade_no': out_trade_no,
            'isJiance': False,
        })

    def checkPayStatus(self, condition, isJiance=True):
        # 外部的isJiance为True表示一定要检测
        res = 'Fail'

        # 查询类型
        checkType = condition['checkType']
        # 第三方订单号
        out_trade_no = condition['out_trade_no']

        # 获取当前登录的用户
        user_id = self.get_session_user_islogin()

        if user_id == False:
            return '未登录！'

        # 根据查询类型查询主数据
        if checkType == 'donate':
            # 捐赠表
            table = self.Charitable_Donate
            typeId = TypeId.charitableDonate.value
        elif checkType == 'titlefund':
            # 基金表
            table = self.Charitable_Donate
            typeId = TypeId.charitableTitleFund.value
        else:
            # 不在类型里，返回非法操作
            return '非法操作！'

        # 查询主数据
        _filter_main = MongoBillFilter()
        _filter_main.match_bill(
            (C('out_trade_no') == out_trade_no)).project({'_id': 0})
        main_data = self.query(
            _filter_main, table)

        # 有没有主数据
        if len(main_data) == 0:
            # 没有主数据，返回非法操作
            return '非法操作！'

        # 判断主数据是否已付款
        # 判断主数据的status是否是通过，防止主数据过了，审批流程没过
        if 'pay_status' in main_data[0] and main_data[0]['status'] == Auditstatus.adopt.value and main_data[0]['pay_status'] == DonatePayStatus.finish.value:
            return DonatePayStatus.finish.value

        # 需要检测的
        if isJiance == True:
            # 在主数据获取第三方支付订单号
            if 'out_trade_no' not in main_data[0]:
                # 没有第三方支付订单号，返回非法操作
                return '非法操作！'

            # 根据第三方订单ID查询数据表的数据
            _filter_trade = MongoBillFilter()
            _filter_trade.match_bill(
                (C('out_trade_no') == main_data[0]['out_trade_no'])).project({'_id': 0})
            trade_data = self.query(
                _filter_trade, 'IEC_third_part_trade_record')

            # 有没有支付数据
            if len(trade_data) == 0:
                # 没有支付数据，返回非法操作
                return '非法操作！'

            if trade_data[0]['pay_status'] == DonatePayStatus.unpay.value:
                # 未付款，不干事
                return DonatePayStatus.unpay.value

        # 正常来说，应该再判断支付金额是否一致的
        # 。。。

        # 暂时来说，捐赠表和基金表这里的流程都是一样的
        # 已付款
        bill_id = self.bill_manage_server2.add_bill(
            OperationType.update.value, typeId, {
                # 主数据ID
                'id': main_data[0]['id'],
                # 支付完成状态
                'pay_status': DonatePayStatus.finish.value,
                # 支付时间
                'pay_time': get_cur_time()
            }, table)
        # 成功的话发送一个消息，创建一个消息数据
        if bill_id:
            if checkType == 'titlefund':
                # 基金表接入了审批流程，需要把审批流程走完
                title_fund_sp = self.update_charitable_title_fund({
                    # 审批标识
                    'is_sp': 1,
                    # 主数据状态
                    'status': Auditstatus.adopt.value,
                    # 审批状态
                    'sp_status': Auditstatus.adopt.value,
                    # 主数据Id
                    'id': main_data[0]['id'],
                    # 第几步，这里是最后一步
                    'step_no': 2,
                })

                if title_fund_sp != 'Success':
                    return title_fund_sp

            # 这里是发送一个消息
            bill_id = self.bill_manage_server2.add_bill(
                OperationType.add.value, TypeId.message.value, {
                    # 标题
                    'message_name': '支付成功',
                    # 内容
                    'message_content': '您有一笔金额为:' + str(main_data[0]['donate_money']) + '的成功到账，感谢您的支持！',
                    # 备注
                    'remark': '支付成功',
                    # 消息类型，默认系统消息
                    'message_type': '77a8e264-ca36-11e9-9a6a-a0a4c57e9ebe',
                    # 推送时间
                    'push_date': get_cur_time(),
                    # 消息创建者
                    'message_creator': user_id,
                    # 接受者
                    'receive_info': [user_id],
                    # 信息状态
                    'message_state': '未读',
                }, self.PT_Message)
            if bill_id:
                res = DonatePayStatus.finish.value

        return res
